package com.glodon.paas.job.monitor.web.controller;

import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_CACULATIONBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_CACULATIONEND_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_DOWNLOADBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_DOWNLOADEND_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_UPLOADBEGIN_TIME;
import static com.glodon.paas.job.JobConstants.PROPERTY_TASK_UPLOADEND_TIME;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.glodon.paas.job.exception.JsonException;
import com.glodon.paas.job.model.MonitorEventType;
import com.glodon.paas.job.model.MonitorStatus;
import com.glodon.paas.job.model.TaskStatus;
import com.glodon.paas.job.monitor.model.ModelStatisticsDTO;
import com.glodon.paas.job.monitor.model.MonitorQueryDTO;
import com.glodon.paas.job.monitor.service.MonitorStatusService;
import com.glodon.paas.job.util.DateFormatUtil;
import com.glodon.paas.job.util.JsonUtil;
import com.glodon.paas.util.DateUtil;

@Controller
public class StatusController {

	private static final Logger		logger	= LoggerFactory.getLogger(StatusController.class);

	@Autowired
	private MonitorStatusService	monitorStatusService;
	private Date					lastWeek;

	public StatusController() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_YEAR, -7);
		lastWeek = cal.getTime();
	}

	@RequestMapping(value = "/status/agent", method = RequestMethod.GET)
	public void agentStatus(Map model) throws Exception {
		List<MonitorStatus> monitorStatusList = monitorStatusService.getMonitorStatus(MonitorEventType.AGENT_STATUS,
				lastWeek);
		List<Map<String, String>> status = monitorStatusToStatus(monitorStatusList);
		model.put("status", status);
	}

	@RequestMapping(value = "/status/server", method = RequestMethod.GET)
	public void serverStatus(Map model) throws Exception {
		List<MonitorStatus> monitorStatusList = monitorStatusService.getMonitorStatus(MonitorEventType.SERVER_STATUS,
				lastWeek);
		List<Map<String, String>> status = serverStatusToStatus(monitorStatusList);
		model.put("status", status);
	}

	@RequestMapping(value = "/status/job", method = RequestMethod.GET)
	public void jobStatus(@RequestParam(value = "id", required = false) String jobId,
			@RequestParam(value = "fromNum", defaultValue = "0") int fromNum,
			@RequestParam(value = "pageNum", defaultValue = "20") int pageNum,
			@RequestParam(value = "from", required = false) String from,
			@RequestParam(value = "to", required = false) String to,
			@RequestParam(value = "typeChoose", required = false) String typeChoose, Map model) throws JsonException,
			UnsupportedEncodingException {
		List<Map<String, String>> status = processJobStatus(jobId, fromNum, pageNum, from, to, typeChoose);
		model.put("status", status);
	}

	@RequestMapping(value = "/status/downLoadJob", method = RequestMethod.GET)
	public void downLoadJob(@RequestParam(value = "id", required = false) String jobId,
			@RequestParam(value = "fromNum", defaultValue = "0") int fromNum,
			@RequestParam(value = "pageNum", defaultValue = "20") int pageNum,
			@RequestParam(value = "from", required = false) String from,
			@RequestParam(value = "to", required = false) String to,
			@RequestParam(value = "typeChoose", required = false) String typeChoose, HttpServletResponse response)
			throws JsonException, UnsupportedEncodingException {
		List<Map<String, String>> status = processJobStatus(jobId, fromNum, pageNum, from, to, typeChoose);
		StringBuffer sb = new StringBuffer();
		String title = null;
		title = Messages.getString("jobTitle");
		sb.append(title).append("\r\n");
		if (status.size() != 0) {
			for (Map<String, String> s : status) {
				sb.append("\t" + s.get("jobId")).append(",").append(s.get("originFilename")).append(",\t")
						.append(s.get("jobType")).append(",\t").append(s.get("jobStatus")).append(",\t")
						.append(s.get("inQuqueTime")).append(",\t").append(s.get("jobServerSumbitTime")).append(",\t")
						.append(s.get("completeTime")).append(",\t")
						.append(s.get("waitDuration") == null ? "" : s.get("waitDuration")).append(",")
						.append(s.get("computeDuration") == null ? "" : s.get("computeDuration")).append("\r\n");
			}
		}
		response.setContentType("application/csv");
		response.setHeader("Content-Disposition", "inline; filename=jobReport.csv");
		PrintWriter out = null;
		try {
			response.setCharacterEncoding("GBK");
			out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "GBK"));
		} catch (UnsupportedEncodingException e) {
			logger.error("downLoadJob(String, String, HttpServletResponse)", e);
		} catch (IOException e) {
			logger.error("downLoadJob(String, String, HttpServletResponse)", e);
		}
		out.print(sb.toString());
		out.close();
	}

	@RequestMapping(value = "/job/jobstatistics", method = RequestMethod.GET)
	public void getJobStatistics(@RequestParam(value = "dateChoose", required = false) String dateChoose, Map model)
			throws Exception {
		String date = null;
		if (StringUtils.isNotEmpty(dateChoose)) {
			if (dateChoose.equals("0")) {
				date = DateUtil.getIntervalHour(-1);
			} else if (dateChoose.equals("1")) {
				date = DateUtil.getIntervalDate(-1);
			} else if (dateChoose.equals("3")) {
				date = DateUtil.getIntervalDate(-3);
			} else if (dateChoose.equals("7")) {
				date = DateUtil.getIntervalDate(-7);
			}
		}
		List<Map<String, String>> mapList = processJobStatus(null, 0, 100, date, null, null);
		NumberFormat nf = NumberFormat.getPercentInstance();
		nf.setMinimumFractionDigits(2);
		Map<String, List<Map<String, String>>> groupByJobTypeMap = buildGroupByTaskTypeMap(mapList);
		List<Map<String, String>> jobStatisticsListMap = new ArrayList<Map<String, String>>(groupByJobTypeMap.size());
		List<ModelStatisticsDTO> jobStatisticsList = buildModelStatisticsList(nf, groupByJobTypeMap,
				jobStatisticsListMap);
		ModelStatisticsDTO jobStatisticsSumDTO = buildModelStatisticsSumDTO(nf, jobStatisticsList);
		Map sumMap = new HashMap();
		if (null != jobStatisticsSumDTO) {
			sumMap = BeanUtils.describe(jobStatisticsSumDTO);
		}
		model.put("sum", sumMap);
		model.put("status", jobStatisticsListMap);
	}

	@RequestMapping(value = "/status/task")
	public void taskStatus(@RequestParam(value = "jobId", required = false) String jobId,
			@RequestParam(value = "fromNum", defaultValue = "0") int fromNum,
			@RequestParam(value = "pageNum", defaultValue = "20") int pageNum,
			@RequestParam(value = "from", required = false) String from,
			@RequestParam(value = "to", required = false) String to,
			@RequestParam(value = "taskTypeChoose", required = false) String taskTypeChoose, Map model)
			throws JsonException, UnsupportedEncodingException {
		MonitorQueryDTO taskQueryDTO = buildMonitorQueryDTO(jobId, fromNum, pageNum, null, from, to, taskTypeChoose);
		List<Object[]> list = monitorStatusService.queryTaskList(taskQueryDTO);
		List<Map<String, String>> status = new ArrayList<Map<String, String>>();
		for (Object[] item : list) {
			HashMap<String, String> taskMap = new HashMap<String, String>();
			buildTaskMap(item, taskMap);
			status.add(taskMap);
		}
		model.put("status", status);
	}

	@RequestMapping(value = "/status/downLoadTask", method = RequestMethod.GET)
	public void downLoadTask(@RequestParam(value = "jobId", required = false) String jobId,
			@RequestParam(value = "fromNum", defaultValue = "0") int fromNum,
			@RequestParam(value = "pageNum", defaultValue = "20") int pageNum,
			@RequestParam(value = "from", required = false) String from,
			@RequestParam(value = "to", required = false) String to,
			@RequestParam(value = "taskTypeChoose", required = false) String taskTypeChoose,
			HttpServletResponse response) {
		MonitorQueryDTO taskQueryDTO = buildMonitorQueryDTO(jobId, fromNum, pageNum, null, from, to, taskTypeChoose);
		List<Object[]> list = monitorStatusService.queryTaskList(taskQueryDTO);
		StringBuffer sb = new StringBuffer();
		String title = null;
		title = Messages.getString("taskTitle");
		sb.append(title).append("\r\n");
		for (Object[] item : list) {
			Map taskInfoMap = new HashMap();
			try {
				taskInfoMap = JsonUtil.jsonToMap(String.valueOf(item[4]));
			} catch (JsonException e) {
				logger.error("downLoadTask(String, String, HttpServletResponse)", e);
			}
			sb.append("\t" + taskInfoMap.get("jobId") == null ? "" : String.valueOf(taskInfoMap.get("jobId")))
					.append(",").append(String.valueOf(item[0])).append(",")
					.append(String.valueOf(item[5] == null ? "" : item[5]));
			String taskStatus = item[3] == null ? "" : String.valueOf(item[3]);
			String agentIp = taskInfoMap.get("agent") == null ? "" : taskInfoMap.get("agent").toString();

			String inQuqueTime = "";
			if ((Date) item[6] != null) {
				inQuqueTime = DateFormatUtil.format((Date) item[6]);
			}
			String downLoadTime = (String) taskInfoMap.get(PROPERTY_TASK_DOWNLOADBEGIN_TIME);
			String computeTime = (String) taskInfoMap.get(PROPERTY_TASK_CACULATIONBEGIN_TIME);
			String uploadTime = (String) taskInfoMap.get(PROPERTY_TASK_UPLOADBEGIN_TIME);
			String endTime = String.valueOf(item[1]);
			sb.append(",")
					.append(taskStatus)
					.append(",")
					.append(agentIp == null ? "" : String.valueOf(agentIp))
					.append(",\t")
					.append(inQuqueTime == null ? "" : inQuqueTime)
					.append(",\t")
					.append(downLoadTime == null ? "" : downLoadTime)
					.append(",\t")
					.append(computeTime == null ? "" : computeTime)
					.append(",\t")
					.append(uploadTime == null ? "" : uploadTime)
					.append(",\t")
					.append(endTime == null ? "" : endTime)
					.append(taskInfoMap.get("errorMsg") == null ? "" : String.valueOf(taskInfoMap.get("errorMsg"))
							.replaceAll(",", "|")).append("\r\n");
		}
		response.setContentType("application/csv");
		response.setHeader("Content-Disposition", "inline; filename=taskReport.csv");
		PrintWriter out = null;
		try {
			response.setCharacterEncoding("GBK");
			out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), "GBK"));

		} catch (UnsupportedEncodingException e) {
			logger.error("downLoadTask(String, String, HttpServletResponse)", e);
		} catch (IOException e) {
			logger.error("downLoadTask(String, String, HttpServletResponse)", e);
		}
		out.print(sb.toString());
		out.close();
	}

	@RequestMapping(value = "/task/taskDetail", method = RequestMethod.GET)
	public @ResponseBody
	String getTaskDetail(@RequestParam("taskId") String taskId) throws Exception {
		MonitorQueryDTO taskQueryDTO = buildMonitorQueryDTO(taskId, 0, 100, null, null, null, null);
		List<Object[]> list = monitorStatusService.queryTaskList(taskQueryDTO);
		HashMap<String, String> taskMap = new HashMap<String, String>();
		for (Object[] item : list) {
			buildTaskMap(item, taskMap);
		}
		return JsonUtil.mapToJson(taskMap);
	}

	@RequestMapping(value = "/task/taskstatistics", method = RequestMethod.GET)
	public void getTaskStatistics(@RequestParam(value = "dateChoose", required = false) String dateChoose, Map model)
			throws Exception {
		String date = null;
		if (StringUtils.isNotEmpty(dateChoose)) {
			if (dateChoose.equals("0")) {
				date = DateUtil.getIntervalHour(-1);
			} else if (dateChoose.equals("1")) {
				date = DateUtil.getIntervalDate(-1);
			} else if (dateChoose.equals("3")) {
				date = DateUtil.getIntervalDate(-3);
			} else if (dateChoose.equals("7")) {
				date = DateUtil.getIntervalDate(-7);
			}
		}

		MonitorQueryDTO taskQueryDTO = buildMonitorQueryDTO(null, 0, 100, null, date, null, null);
		List<Object[]> list = monitorStatusService.queryTaskList(taskQueryDTO);
		List<Map<String, String>> mapList = new ArrayList<Map<String, String>>(list.size());
		for (Object[] item : list) {
			HashMap<String, String> taskMap = new HashMap<String, String>();
			buildTaskMap(item, taskMap);
			mapList.add(taskMap);
		}
		NumberFormat nf = NumberFormat.getPercentInstance();
		nf.setMinimumFractionDigits(2);
		Map<String, List<Map<String, String>>> groupByTaskTypeMap = buildGroupByTaskTypeMap(mapList);
		List<Map<String, String>> taskStatisticsListMap = new ArrayList<Map<String, String>>(groupByTaskTypeMap.size());
		List<ModelStatisticsDTO> taskStatisticsList = buildModelStatisticsList(nf, groupByTaskTypeMap,
				taskStatisticsListMap);
		ModelStatisticsDTO taskStatisticsSumDTO = buildModelStatisticsSumDTO(nf, taskStatisticsList);
		Map sumMap = new HashMap();
		if (null != taskStatisticsSumDTO) {
			sumMap = BeanUtils.describe(taskStatisticsSumDTO);
		}
		model.put("sum", sumMap);
		model.put("status", taskStatisticsListMap);
	}

	private List<Map<String, String>> serverStatusToStatus(List<MonitorStatus> monitorStatusList) {
		List<Map<String, String>> status = new ArrayList<Map<String, String>>();
		for (MonitorStatus monitorStatus : monitorStatusList) {
			HashMap<String, String> s = new HashMap<String, String>();
			s.put("address", monitorStatus.getTraceId());
			s.put("startTime", DateFormatUtil.format(monitorStatus.getCreatedTime()));
			s.put("updateTime", DateFormatUtil.format(monitorStatus.getUpdatedTime()));
			if (monitorStatus.getJson() != null) {
				String ip = monitorStatus.getValues().get("ip") == null ? "" : (String) monitorStatus.getValues().get(
						"ip");
				s.put("ip", ip);
				String statusCode = monitorStatus.getValues().get("statusCode") == null ? "" : (String) monitorStatus
						.getValues().get("statusCode");
				s.put("statusCode", statusCode);
				String appName = monitorStatus.getValues().get("appName") == null ? "" : (String) monitorStatus
						.getValues().get("appName");
				s.put("appName", appName);
				String env = monitorStatus.getValues().get("env") == null ? "" : (String) monitorStatus.getValues()
						.get("env");
				s.put("env", env);
				String healthMessage = monitorStatus.getValues().get("healthMessage") == null ? ""
						: (String) monitorStatus.getValues().get("healthMessage");
				s.put("healthMessage", healthMessage);
			}
			status.add(s);
		}
		return status;
	}

	private List<Map<String, String>> processJobStatus(String jobId, int fromNum, int pageNum, String from, String to,
			String typeChoose) throws JsonException, UnsupportedEncodingException {
		MonitorQueryDTO taskQueryDTO = buildMonitorQueryDTO(jobId, fromNum, pageNum, null, from, to, typeChoose);
		List<Object[]> list = monitorStatusService.queryTaskList(taskQueryDTO);
		LinkedHashMap<String, Set<Map<String, String>>> jobMap = new LinkedHashMap<String, Set<Map<String, String>>>(
				list.size());
		for (Object[] item : list) {
			Map<String, String> taskMap = new HashMap<String, String>();
			buildTaskMap(item, taskMap);
			String monitorJobId = (String) taskMap.get("jobId");
			if (jobMap.get(monitorJobId) == null) {
				Set<Map<String, String>> taskSet = new HashSet<Map<String, String>>();
				taskSet.add(taskMap);
				jobMap.put(monitorJobId, taskSet);
			} else {
				Set<Map<String, String>> taskSet = jobMap.get(monitorJobId);
				taskSet.add(taskMap);
				jobMap.remove(monitorJobId);
				jobMap.put(monitorJobId, taskSet);
			}
		}
		List<Map<String, String>> status = new ArrayList<Map<String, String>>();
		buildStatusList(jobMap, status);
		return status;
	}

	private void buildStatusList(LinkedHashMap<String, Set<Map<String, String>>> jobMap,
			List<Map<String, String>> status) {
		if (null != jobMap && !jobMap.isEmpty()) {
			for (Map.Entry<String, Set<Map<String, String>>> entry : jobMap.entrySet()) {
				Map<String, String> statusMap = new HashMap<String, String>();
				String monitorJobId = entry.getKey();
				Set<Map<String, String>> taskSet = entry.getValue();
				int createdSize = 0;
				int runningSize = 0;
				int successSize = 0;
				int failureSize = 0;
				int canceledSize = 0;
				int i = 0;
				long waitDuration = 0l;
				long computeDuration = 0l;
				for (Map<String, String> taskMap : taskSet) {
					i++;
					if (null == statusMap.get("taskType") && null != taskMap.get("taskType")) {
						String taskType = (String) taskMap.get("taskType");
						if (taskType.indexOf("gcl") != -1) {
							taskType = "gcl";
						}
						statusMap.put("taskType", taskType);// 工作类型
					}

					if (null == statusMap.get("originFilename") && null != taskMap.get("originFilename")) {
						String originFilename = (String) taskMap.get("originFilename");
						statusMap.put("originFilename", originFilename);// 文件名称
					}

					if (i == taskSet.size()) {
						if (null != taskMap.get("inQuqueTime")) {
							statusMap.put("inQuqueTime", taskMap.get("inQuqueTime"));// 提交时间
						}
						if (null != taskMap.get("jobServerSumbitTime")) {
							statusMap.put("jobServerSumbitTime", taskMap.get("jobServerSumbitTime"));// 创建时间
						}
						if (null != taskMap.get("computeTime")) {
							statusMap.put("computeTime", taskMap.get("computeTime"));// 该Job的第一个Task的开始处理时间
						}
					}
					if (i == 1 && null != taskMap.get("endTime")) {
						statusMap.put("completeTime", taskMap.get("endTime"));// 该Job的最后一个Task的完成时间
					}
					String taskStatus = taskMap.get("taskStatus");
					if (StringUtils.isNotBlank(taskStatus)) {
						if (taskStatus.equals(TaskStatus.created.toString())) {
							createdSize++;
						} else if (taskStatus.equals(TaskStatus.running.toString())) {
							runningSize++;
						} else if (taskStatus.equals(TaskStatus.success.toString())) {
							successSize++;
						} else if (taskStatus.equals(TaskStatus.failure.toString())) {
							failureSize++;
						} else if (taskStatus.equals(TaskStatus.canceled.toString())) {
							canceledSize++;
						}
					}
					if (null != taskMap.get("waitDuration")) {
						String taskWaitDuration = taskMap.get("waitDuration");
						waitDuration = waitDuration + Long.valueOf(taskWaitDuration).longValue();
					}
					if (null != taskMap.get("computeDuration")) {
						String taskComputeDuration = taskMap.get("computeDuration");
						computeDuration = computeDuration + Long.valueOf(taskComputeDuration).longValue();
					}
				}
				statusMap.put("jobId", monitorJobId);// 工作编号
				statusMap.put("taskSize", String.valueOf(taskSet.size()));// 任务数

				// 工作状态
				if (createdSize == taskSet.size()) {
					statusMap.put("jobStatus", TaskStatus.created.toString());
				} else if (runningSize == taskSet.size()) {
					statusMap.put("jobStatus", TaskStatus.running.toString());
				} else if (successSize == taskSet.size()) {
					statusMap.put("jobStatus", TaskStatus.success.toString());
				} else if (failureSize == taskSet.size()) {
					statusMap.put("jobStatus", TaskStatus.failure.toString());
				} else if (canceledSize == taskSet.size()) {
					statusMap.put("jobStatus", TaskStatus.canceled.toString());
				} else {
					if (runningSize > 0 && runningSize < taskSet.size()) {
						statusMap.put("jobStatus", TaskStatus.running.toString());
					} else if (failureSize > 0 && failureSize < taskSet.size()) {
						statusMap.put("jobStatus", TaskStatus.failure.toString());
					} else if (canceledSize > 0 && canceledSize < taskSet.size()) {
						statusMap.put("jobStatus", TaskStatus.canceled.toString());
					}
				}
				if (null != statusMap.get("jobStatus")) {
					statusMap.put("modelStatus", statusMap.get("jobStatus"));
				}
				statusMap.put("computeDuration", String.valueOf(computeDuration));
				statusMap.put("waitDuration", String.valueOf(waitDuration));
				status.add(statusMap);
			}
		}
	}

	private Map<String, List<Map<String, String>>> buildGroupByTaskTypeMap(List<Map<String, String>> mapList) {
		Map<String, List<Map<String, String>>> groupByTaskTypeMap = new HashMap<String, List<Map<String, String>>>();
		if (null != mapList && !mapList.isEmpty()) {
			for (Map<String, String> map : mapList) {
				String taskType = (String) map.get("taskType");
				if (taskType.indexOf("gcl") != -1) {
					taskType = "gcl";
				}
				if (null == groupByTaskTypeMap.get(taskType)) {
					List<Map<String, String>> groupByTaskTypeList = new ArrayList<Map<String, String>>();
					groupByTaskTypeList.add(map);
					groupByTaskTypeMap.put(taskType, groupByTaskTypeList);
				} else {
					List<Map<String, String>> groupByTaskTypeList = groupByTaskTypeMap.get(taskType);
					groupByTaskTypeList.add(map);
					groupByTaskTypeMap.remove(taskType);
					groupByTaskTypeMap.put(taskType, groupByTaskTypeList);
				}
			}
		}
		return groupByTaskTypeMap;
	}

	private List<ModelStatisticsDTO> buildModelStatisticsList(NumberFormat nf,
			Map<String, List<Map<String, String>>> groupByModelTypeMap, List<Map<String, String>> modelStatisticsListMap)
			throws Exception {
		List<ModelStatisticsDTO> modelStatisticsList = new ArrayList<ModelStatisticsDTO>(groupByModelTypeMap.size());
		for (Map.Entry<String, List<Map<String, String>>> entry : groupByModelTypeMap.entrySet()) {
			List<Map<String, String>> modelTypeList = entry.getValue();
			ModelStatisticsDTO modelStatisticsDTO = new ModelStatisticsDTO();
			modelStatisticsDTO.setTaskType(entry.getKey());
			long[] waitDurationArray = new long[modelTypeList.size()];
			long waitDurationSum = 0;
			long[] computeDurationArray = new long[modelTypeList.size()];
			long computeDurationSum = 0;
			int i = 0;
			for (Map<String, String> map : modelTypeList) {
				String modelStatus = (String) map.get("modelStatus");
				String waitDuration = (String) map.get("waitDuration");
				String computeDuration = (String) map.get("computeDuration");
				if (TaskStatus.created.toString().equals(modelStatus)
						|| TaskStatus.running.toString().equals(modelStatus)) {// 当前未完成的任务总数量
					modelStatisticsDTO.setNotFinishTaskNum(modelStatisticsDTO.getNotFinishTaskNum() + 1);
				}
				if (TaskStatus.created.toString().equals(modelStatus)) {// 等待任务数量
					modelStatisticsDTO.setWaitTaskNum(modelStatisticsDTO.getWaitTaskNum() + 1);
				}
				if (TaskStatus.running.toString().equals(modelStatus)) {// 正在处理任务数量
					modelStatisticsDTO.setRunningTaskNum(modelStatisticsDTO.getRunningTaskNum() + 1);
				}
				if (TaskStatus.success.toString().equals(modelStatus)
						|| TaskStatus.failure.toString().equals(modelStatus)
						|| TaskStatus.canceled.toString().equals(modelStatus)) {// 完成的任务数量
					modelStatisticsDTO.setFinishTaskNum(modelStatisticsDTO.getFinishTaskNum() + 1);
				}
				if (TaskStatus.success.toString().equals(modelStatus)) {// 成功的任务数量
					modelStatisticsDTO.setSuccessTaskNum(modelStatisticsDTO.getSuccessTaskNum() + 1);
				}
				if (TaskStatus.failure.toString().equals(modelStatus)) {// 失败的任务数量
					modelStatisticsDTO.setFailureTaskNum(modelStatisticsDTO.getFailureTaskNum() + 1);
				}
				waitDurationArray[i] = Long.valueOf(waitDuration);
				waitDurationSum = waitDurationSum + waitDurationArray[i];

				computeDurationArray[i] = Long.valueOf(computeDuration);
				computeDurationSum = computeDurationSum + computeDurationArray[i];

				i++;
			}

			if (null != modelTypeList && !modelTypeList.isEmpty()) {
				modelStatisticsDTO.setSumTaskNum(modelTypeList.size());
				double sumTaskNum = (double) modelStatisticsDTO.getSumTaskNum();
				modelStatisticsDTO.setWaitRate(nf.format((double) modelStatisticsDTO.getWaitTaskNum() / sumTaskNum));// 等待率(等待任务数量/总任务数量)
				modelStatisticsDTO.setRunningRate(nf.format((double) modelStatisticsDTO.getRunningTaskNum()
						/ sumTaskNum));// 处理率=正在处理任务数量/总任务数量
				modelStatisticsDTO
						.setFinishRate(nf.format((double) modelStatisticsDTO.getFinishTaskNum() / sumTaskNum));// 完成率=完成的任务数量/总任务数量
				modelStatisticsDTO.setSuccessRate(nf.format((double) modelStatisticsDTO.getSuccessTaskNum()
						/ sumTaskNum));// 成功率=成功的任务数量/总任务数量
				modelStatisticsDTO.setFailureRate(nf.format((double) modelStatisticsDTO.getFailureTaskNum()
						/ sumTaskNum));// 失败率=失败的任务数量/总任务数量

				Arrays.sort(waitDurationArray);
				modelStatisticsDTO.setMinWaitDuration(waitDurationArray[0]);// 最小等待时间
				modelStatisticsDTO.setMaxWaitDuration(waitDurationArray[modelTypeList.size() - 1]);// 最大等待时间
				modelStatisticsDTO.setAvgWaitDuration(waitDurationSum / modelTypeList.size());// 平均等待时间

				Arrays.sort(computeDurationArray);
				modelStatisticsDTO.setMinComputeDuration(computeDurationArray[0]);// 最小处理时间
				modelStatisticsDTO.setMaxComputeDuration(computeDurationArray[modelTypeList.size() - 1]);// 最大处理时间
				modelStatisticsDTO.setAvgComputeDuration(computeDurationSum / modelTypeList.size());// 平均处理时间
			}
			modelStatisticsList.add(modelStatisticsDTO);
			Map descMap = BeanUtils.describe(modelStatisticsDTO);
			modelStatisticsListMap.add(descMap);
		}
		return modelStatisticsList;
	}

	private ModelStatisticsDTO buildModelStatisticsSumDTO(NumberFormat nf, List<ModelStatisticsDTO> modelStatisticsList) {
		ModelStatisticsDTO modelStatisticsSumDTO = null;
		if (null != modelStatisticsList && !modelStatisticsList.isEmpty()) {
			modelStatisticsSumDTO = new ModelStatisticsDTO();
			for (ModelStatisticsDTO modelStatisticsDTO : modelStatisticsList) {
				modelStatisticsSumDTO.setSumTaskNum(modelStatisticsSumDTO.getSumTaskNum()
						+ modelStatisticsDTO.getSumTaskNum());
				modelStatisticsSumDTO.setNotFinishTaskNum(modelStatisticsSumDTO.getNotFinishTaskNum()
						+ modelStatisticsDTO.getNotFinishTaskNum());
				modelStatisticsSumDTO.setWaitTaskNum(modelStatisticsSumDTO.getWaitTaskNum()
						+ modelStatisticsDTO.getWaitTaskNum());
				modelStatisticsSumDTO.setRunningTaskNum(modelStatisticsSumDTO.getRunningTaskNum()
						+ modelStatisticsDTO.getRunningTaskNum());
				modelStatisticsSumDTO.setFinishTaskNum(modelStatisticsSumDTO.getFinishTaskNum()
						+ modelStatisticsDTO.getFinishTaskNum());
				modelStatisticsSumDTO.setSuccessTaskNum(modelStatisticsSumDTO.getSuccessTaskNum()
						+ modelStatisticsDTO.getSuccessTaskNum());
				modelStatisticsSumDTO.setFailureTaskNum(modelStatisticsSumDTO.getFailureTaskNum()
						+ modelStatisticsDTO.getFailureTaskNum());
				modelStatisticsSumDTO.setMinWaitDuration(modelStatisticsSumDTO.getMinWaitDuration()
						+ modelStatisticsDTO.getMinWaitDuration());
				modelStatisticsSumDTO.setMaxWaitDuration(modelStatisticsSumDTO.getMaxWaitDuration()
						+ modelStatisticsDTO.getMaxWaitDuration());
				modelStatisticsSumDTO.setAvgWaitDuration(modelStatisticsSumDTO.getAvgWaitDuration()
						+ modelStatisticsDTO.getAvgWaitDuration());
				modelStatisticsSumDTO.setMinComputeDuration(modelStatisticsSumDTO.getMinComputeDuration()
						+ modelStatisticsDTO.getMinComputeDuration());
				modelStatisticsSumDTO.setMaxComputeDuration(modelStatisticsSumDTO.getMaxComputeDuration()
						+ modelStatisticsDTO.getMaxComputeDuration());
				modelStatisticsSumDTO.setAvgComputeDuration(modelStatisticsSumDTO.getAvgComputeDuration()
						+ modelStatisticsDTO.getAvgComputeDuration());

			}
			double sumTaskNum = (double) modelStatisticsSumDTO.getSumTaskNum();
			modelStatisticsSumDTO.setWaitRate(nf.format((double) modelStatisticsSumDTO.getWaitTaskNum() / sumTaskNum));
			modelStatisticsSumDTO.setRunningRate(nf.format((double) modelStatisticsSumDTO.getRunningTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setFinishRate(nf.format((double) modelStatisticsSumDTO.getFinishTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setSuccessRate(nf.format((double) modelStatisticsSumDTO.getSuccessTaskNum()
					/ sumTaskNum));
			modelStatisticsSumDTO.setFailureRate(nf.format((double) modelStatisticsSumDTO.getFailureTaskNum()
					/ sumTaskNum));
		}
		return modelStatisticsSumDTO;
	}

	private MonitorQueryDTO buildMonitorQueryDTO(String id, int fromNum, int pageNum, String fileName, String from,
			String to, String typeChoose) {
		if (StringUtils.isNotBlank(from)) {
			from = from + " 00:00:00";
			Date fromDate = DateUtil.getDate(from, DateUtil.DAFAULT_DATETIME_FORMAT);
			from = DateUtil.formatDate(fromDate, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		if (StringUtils.isNotBlank(to)) {
			to = to + " 23:59:59";
			Date toDate = DateUtil.getDate(to, DateUtil.DAFAULT_DATETIME_FORMAT);
			to = DateUtil.formatDate(toDate, DateUtil.DAFAULT_DATETIME_FORMAT);
		}

		MonitorQueryDTO taskQueryDTO = new MonitorQueryDTO();
		taskQueryDTO.setFileName(fileName);
		taskQueryDTO.setFromDate(from);
		taskQueryDTO.setFromNum(fromNum);
		taskQueryDTO.setId(id);
		taskQueryDTO.setPageNum(pageNum);
		taskQueryDTO.setType(typeChoose);
		taskQueryDTO.setToDate(to);
		return taskQueryDTO;
	}

	private void buildTaskMap(Object[] item, Map<String, String> taskMap) throws JsonException,
			UnsupportedEncodingException {
		taskMap.put("taskId", String.valueOf(item[0]));
		taskMap.put("taskType", String.valueOf(item[5] == null ? "" : item[5]));
		Map taskInfoMap = new HashMap();
		try {
			taskInfoMap = JsonUtil.jsonToMap(String.valueOf(item[4] == null ? "{}" : item[4]));
		} catch (JsonException e) {
			throw new JsonException("Can not convert json to map.", e);
		}
		taskMap.put("jobId", taskInfoMap.get("jobId") == null ? "" : String.valueOf(taskInfoMap.get("jobId")));
		taskMap.put("agentIp", taskInfoMap.get("agent") == null ? "" : String.valueOf(taskInfoMap.get("agent")));
		taskMap.put(
				"originFilename",
				taskInfoMap.get("originFilename") == null ? "" : URLDecoder.decode(
						String.valueOf(taskInfoMap.get("originFilename")), "UTF-8"));
		String taskStatus = item[3] == null ? "" : String.valueOf(item[3]);
		String tires = null;
		if (taskInfoMap.get("stories") != null) {
			tires = taskInfoMap.get("stories").toString().replaceAll(",", "|");
		}

		String inQuqueTime = "";
		Date startTime = null;
		if (item[6] != null) {
			startTime = (Date) item[6];
			inQuqueTime = DateFormatUtil.format((Date) item[6]);
		}

		String jobServerSumbitTime = "";
		if (item[7] != null) {
			jobServerSumbitTime = DateFormatUtil.format((Date) item[7]);
		}

		String downLoadTime = (String) taskInfoMap.get(PROPERTY_TASK_DOWNLOADBEGIN_TIME);
		Date downLoadDateTime = null;
		if (StringUtils.isNotBlank(downLoadTime)) {
			downLoadDateTime = DateUtil.getDate(downLoadTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			downLoadTime = DateUtil.formatDate(downLoadDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String downLoadEndTime = (String) taskInfoMap.get(PROPERTY_TASK_DOWNLOADEND_TIME);
		Date downLoadEndDateTime = null;
		if (StringUtils.isNotBlank(downLoadEndTime)) {
			downLoadEndDateTime = DateUtil.getDate(downLoadEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			downLoadEndTime = DateUtil.formatDate(downLoadEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		long downLoadDuration = 0l;
		if (null != downLoadDateTime && null != downLoadEndDateTime) {
			downLoadDuration = downLoadEndDateTime.getTime() - downLoadDateTime.getTime();
		}

		String computeTime = (String) taskInfoMap.get(PROPERTY_TASK_CACULATIONBEGIN_TIME);
		Date computeDateTime = null;
		if (StringUtils.isNotBlank(computeTime)) {
			computeDateTime = DateUtil.getDate(computeTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			computeTime = DateUtil.formatDate(computeDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String computeEndTime = (String) taskInfoMap.get(PROPERTY_TASK_CACULATIONEND_TIME);
		Date computeEndDateTime = null;
		if (StringUtils.isNotBlank(computeEndTime)) {
			computeEndDateTime = DateUtil.getDate(computeEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			computeEndTime = DateUtil.formatDate(computeEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}

		long computeDuration = 0l;
		if (TaskStatus.success.toString().equals(taskStatus) || TaskStatus.failure.toString().equals(taskStatus)) {
			if (null != computeDateTime && null != computeEndDateTime) {
				computeDuration = computeEndDateTime.getTime() - computeDateTime.getTime();
			}
		} else {
			if (null != computeDateTime) {
				computeDuration = System.currentTimeMillis() - computeDateTime.getTime();
			}
		}

		String uploadTime = (String) taskInfoMap.get(PROPERTY_TASK_UPLOADBEGIN_TIME);
		Date uploadDateTime = null;
		if (StringUtils.isNotBlank(uploadTime)) {
			uploadDateTime = DateUtil.getDate(uploadTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			uploadTime = DateUtil.formatDate(uploadDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		String upLoadEndTime = (String) taskInfoMap.get(PROPERTY_TASK_UPLOADEND_TIME);
		Date uploadEndDateTime = null;
		if (StringUtils.isNotBlank(upLoadEndTime)) {
			uploadEndDateTime = DateUtil.getDate(upLoadEndTime, DateUtil.DAFAULT_DATETIME_FORMAT);
			upLoadEndTime = DateUtil.formatDate(uploadEndDateTime, DateUtil.DAFAULT_DATETIME_FORMAT);
		}
		long uploadDuration = 0l;
		if (null != uploadDateTime && null != uploadEndDateTime) {
			uploadDuration = uploadEndDateTime.getTime() - uploadDateTime.getTime();
		}

		String endTime = String.valueOf(item[1] == null ? "" : item[1]);
		if (StringUtils.isNotBlank(endTime)) {
			endTime = DateUtil.formatDate(DateUtil.getDate(endTime, DateUtil.DAFAULT_DATETIME_FORMAT),
					DateUtil.DAFAULT_DATETIME_FORMAT);
		}

		long waitDuration = 0l;
		if (TaskStatus.running.toString().equals(taskStatus) || TaskStatus.success.toString().equals(taskStatus)
				|| TaskStatus.failure.toString().equals(taskStatus)) {
			if (null != computeDateTime && null != startTime) {
				waitDuration = computeDateTime.getTime() - startTime.getTime();
			}
		} else {
			if (null != startTime) {
				waitDuration = System.currentTimeMillis() - startTime.getTime();
			}
		}
		taskMap.put("taskStatus", taskStatus);
		taskMap.put("modelStatus", taskStatus);
		taskMap.put("countTires", tires == null ? "" : tires.toString());
		taskMap.put("inQuqueTime", inQuqueTime);
		taskMap.put("jobServerSumbitTime", jobServerSumbitTime);
		taskMap.put("downLoadTime", downLoadTime == null ? "" : downLoadTime);
		taskMap.put("downLoadDuration", String.valueOf(downLoadDuration));
		taskMap.put("computeTime", computeTime == null ? "" : computeTime);
		taskMap.put("computeDuration", String.valueOf(computeDuration));
		taskMap.put("uploadTime", uploadTime == null ? "" : uploadTime);
		taskMap.put("uploadDuration", String.valueOf(uploadDuration));
		taskMap.put("endTime", endTime);
		taskMap.put("waitDuration", String.valueOf(waitDuration));
		taskMap.put("errorMsg", taskInfoMap.get("errorMsg") == null ? "" : String.valueOf(taskInfoMap.get("errorMsg")));
	}

	private List<Map<String, String>> monitorStatusToStatus(List<MonitorStatus> monitorStatusList) {
		List<Map<String, String>> status = new ArrayList<Map<String, String>>();
		for (MonitorStatus monitorStatus : monitorStatusList) {
			HashMap<String, String> s = new HashMap<String, String>();
			s.put("address", monitorStatus.getTraceId());
			s.put("startTime", DateFormatUtil.format(monitorStatus.getCreatedTime()));
			s.put("updateTime", DateFormatUtil.format(monitorStatus.getUpdatedTime()));
			String success = monitorStatus.getValue("success");
			s.put("success", success == null ? "0" : success);
			String failure = monitorStatus.getValue("failure");
			s.put("failure", failure == null ? "0" : failure);
			String jobId = "";
			String taskId = "";
			String progress = "";
			if (monitorStatus.getJson() != null) {
				String taskInfo = monitorStatus.getValues().get("taskInfo") == null ? "{}" : JsonUtil
						.mapToJson((Map) monitorStatus.getValues().get("taskInfo"));
				Map task = new HashMap();
				try {
					task = JsonUtil.jsonToMap(taskInfo);
				} catch (JsonException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				taskId = task.get("taskId") == null ? "" : task.get("taskId").toString();
				if (task.get("values") != null) {
					jobId = ((Map) task.get("values")).get("jobId") == null ? "" : ((Map) task.get("values")).get(
							"jobId").toString();
					progress = ((Map) task.get("values")).get("progress") == null ? "" : ((Map) task.get("values"))
							.get("progress").toString();
				}
			}
			String workerType = monitorStatus.getValue("workerType");
			s.put("workerType", workerType == null ? " " : workerType);
			if (null != failure || !StringUtils.equals(progress, "100")) {
				s.put("jobId", jobId);
				s.put("taskId", taskId);
			}
			status.add(s);
		}
		return status;
	}

	@RequestMapping(value = "/status/jobDetail", method = RequestMethod.GET)
	public @ResponseBody
	String getJobDetail(@RequestParam("id") String jobId, HttpServletResponse response) throws JsonException {
		List<Object[]> list = monitorStatusService.getJobDetailsById(MonitorEventType.JOB_STATUS, jobId);
		Map<String, List<Map<String, String>>> resultMap = new HashMap<String, List<Map<String, String>>>();
		List<Map<String, String>> itemList = new ArrayList<Map<String, String>>();
		String jobStatus = TaskStatus.success.toString();
		for (Object[] item : list) {
			Map<String, String> itemMap = new HashMap<String, String>();
			itemMap.put("type", item[6] == null ? "" : String.valueOf(item[6]));
			Map taskInfoMap = new HashMap();

			try {
				taskInfoMap = JsonUtil.jsonToMap(String.valueOf(item[5] == null ? "{}" : item[5]));
			} catch (JsonException e) {
				throw new JsonException("Can not convert json to map.", e);
			}
			itemMap.put("progress",
					taskInfoMap.get("progress") == null ? "" : String.valueOf(taskInfoMap.get("progress")));
			String tires = "";
			if (taskInfoMap.get("stories") != null) {
				tires = taskInfoMap.get("stories").toString().replaceAll(",", "|");
			}
			String message = taskInfoMap.get("message") == null ? "" : taskInfoMap.get("message").toString();
			itemMap.put("message", "Process " + tires + " " + message);
			String taskStatus = item[4] == null ? "" : String.valueOf(item[4]);
			itemMap.put("status", taskStatus);
			if (!taskStatus.equals(jobStatus)) {
				if (TaskStatus.success.toString().equals(jobStatus)) {
					jobStatus = taskStatus;
				}

			}
			itemList.add(itemMap);
		}

		resultMap.put("tasks", itemList);
		String taskString = JsonUtil.mapToJson(resultMap);
		String statusResult = "{\"status\":\"" + jobStatus + "\"," + taskString.substring(1, taskString.length() - 1)
				+ "}";
		return statusResult;
	}
}
